/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.ui.dialog.calendar;

import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.ecarx.systemui.plugin.utils.LogUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

public class CalendarData {

    private static final String TAG = "CalendarDataPluginCN";

    private static CalendarData calendarData;

    private CalendarData() {
    }

    public static synchronized CalendarData getInstance() {
        if (calendarData == null) {
            calendarData = new CalendarData();
        }
        return calendarData;
    }

    public CalendarData loadData() {
        Calendar currentDate = Calendar.getInstance();
        int curYear = currentDate.get(Calendar.YEAR);
        int curBaseMonth = currentDate.get(Calendar.MONTH);
        int curMonth = curBaseMonth + 1;
        int curDay = currentDate.get(Calendar.DATE);
        int week = currentDate.get(Calendar.DAY_OF_WEEK);
        int week_of_year = currentDate.get(Calendar.WEEK_OF_YEAR);

        if (calendarData.year == curYear &&
                calendarData.month == curMonth &&
                calendarData.day == curDay &&
                calendarData.calendarItemEntities != null &&
                calendarData.calendarItemEntities.size() > 0) {
            return calendarData;
        }

        calendarData.year = curYear;
        calendarData.month = curMonth;
        calendarData.day = curDay;

        calendarData.strYear = String.format(Locale.getDefault(), "%d year", year);
        calendarData.strDateDay = String.format(Locale.getDefault(), "%d Month %d Day", month, day);
        calendarData.cnWeek = getCNWeek(week);
        calendarData.strWeekNum = String.format(Locale.getDefault(), "%d week", week_of_year);
        calendarData.trunkBranchYear = TrunkBranchAnnals.getTrunkBranchYear(year);
        calendarData.twelveAnimal = getTwelveAnimal(year);

        int[] ints = LunarUtil.solarToLunar(year, month, day);
        //[0]农历年        [1]农历月      [2]农历日     [3]是否闰月 0 false : 1 true
        LogUtils.d(TAG, "loadData -- ints.length:" + ints.length +
                "--农历年:" + ints[0] + "--农历月:" + ints[1] +
                "--农历日:" + ints[2] + "--是否闰月:" + (ints[3] == 1)
        );
        calendarData.nlYear = ints[0] + "年";
        calendarData.nlMonth = LunarUtil.numToChineseMonth(ints[1], ints[3]);
        calendarData.nlDay = LunarUtil.numToChineseDay(ints[2]);
        calendarData.monthDaysCount = LunarUtil.getMonthDaysCount(year, month);
        String[] solarTerms = SolarTermUtil.getSolarTerms(year);
        HashMap<String, String> solar24Map = new HashMap<>();
        for (String solarTerm : solarTerms) {
            String[] split = solarTerm.split("-");
            solar24Map.put(split[0], split[1]);
        }
        calendarData.solar24Terms = solar24Map;

        Calendar tempCal = Calendar.getInstance();
        tempCal.set(curYear, curBaseMonth, 1);
        int firstDayWeek = tempCal.get(Calendar.DAY_OF_WEEK);
        calendarData.beginIndex = getBeginIndex(firstDayWeek);
        calendarData.calendarItemEntities = getCalendarItems(
                calendarData.year, calendarData.month,
                calendarData.day, beginIndex, calendarData.monthDaysCount);
        return calendarData;
    }

    private List<CalendarItemEntity> getCalendarItems(int year, int month, int curDay, int beginIndex, int curtMonthTotalDays) {
        List<CalendarItemEntity> calendarItemEntities = new ArrayList<>();
        if (beginIndex > 0) {
            int[] lastYM = getLastMonthAndYear(year, month);
            int lastYear = lastYM[0];
            int lastMonth = lastYM[1];
            //上个月的天数
            int monthDaysCount = LunarUtil.getMonthDaysCount(lastYear, lastMonth);
            int nextBeginDay = monthDaysCount - beginIndex + 1;
            for (int i = 0; i < beginIndex; i++) {
                //这里主要添加上个月数据
                CalendarItemEntity calendarItemEntity = new CalendarItemEntity();
                calendarItemEntity.setIsLastOrNext(-1);
                int lastYlDay = nextBeginDay + i;
                calendarItemEntity.setYlDay(lastYlDay);
                int[] ints = LunarUtil.solarToLunar(lastYear, lastMonth, lastYlDay);
                int nlDay = ints[2];
                String strNlMonth = LunarUtil.numToChineseMonth(ints[1], ints[3]);
                String strNlDay = LunarUtil.numToChineseDay(nlDay);
                if (nlDay == 1) {
                    calendarItemEntity.setNlDay(strNlMonth);
                } else {
                    calendarItemEntity.setNlDay(strNlDay);
                }
                calendarItemEntity.setNlDay(strNlDay);
                String solarFestival = getSolarFestival(ints, strNlMonth+strNlMonth, lastYear, lastMonth, lastYlDay);
                calendarItemEntity.setFestival(solarFestival);

                calendarItemEntity.setCurrentDay(false);
                calendarItemEntities.add(calendarItemEntity);
            }
        }
        int currentDayIndex = 0;
        for (int i = 0; i < curtMonthTotalDays; i++) {
            CalendarItemEntity calendarItemEntity = new CalendarItemEntity();
            calendarItemEntity.setIsLastOrNext(0);
            int ylDay = i + 1;
            calendarItemEntity.setYlDay(ylDay);
            int[] ints = LunarUtil.solarToLunar(year, month, ylDay);
            int nlDay = ints[2];
            String strNlMonth = LunarUtil.numToChineseMonth(ints[1], ints[3]);
            String strNlDay = LunarUtil.numToChineseDay(nlDay);
            if (nlDay == 1) {
                calendarItemEntity.setNlDay(strNlMonth);
            } else {
                calendarItemEntity.setNlDay(strNlDay);
            }
            String solarFestival = getSolarFestival(ints, strNlMonth+strNlDay, year, month, ylDay);
            calendarItemEntity.setFestival(solarFestival);

            boolean isCurrentDay = (curDay == ylDay);
            calendarItemEntity.setCurrentDay(isCurrentDay);
            calendarItemEntities.add(calendarItemEntity);
            if (isCurrentDay) {
                currentDayIndex = calendarItemEntities.size() - 1;
                calendarData.currentFestival = solarFestival;
            }
        }

        int size2 = calendarItemEntities.size();
        int mo = size2 % 7;
        int hasAddCount;
        if (mo == 0) {
            hasAddCount = mo;
        } else {
            hasAddCount = 7 - mo;
        }
        if (hasAddCount > 0) {
            int[] nextMonthAndYear = getNextMonthAndYear(year, month);
            int nextYear = nextMonthAndYear[0];
            int nextMonth = nextMonthAndYear[1];
            for (int i = 0; i < hasAddCount; i++) {
                CalendarItemEntity calendarItemEntity = new CalendarItemEntity();
                calendarItemEntity.setIsLastOrNext(1);
                int nextYlDay = i + 1;
                calendarItemEntity.setYlDay(nextYlDay);
                int[] ints = LunarUtil.solarToLunar(nextYear, nextMonth, nextYlDay);
                int nlDay = ints[2];
                String strNlMonth = LunarUtil.numToChineseMonth(ints[1], ints[3]);
                String strNlDay = LunarUtil.numToChineseDay(nlDay);
                if (nlDay == 1) {
                    calendarItemEntity.setNlDay(strNlMonth);
                } else {
                    calendarItemEntity.setNlDay(strNlDay);
                }
                String solarFestival = getSolarFestival(ints, strNlMonth+strNlDay, nextYear, nextMonth, nextYlDay);
                calendarItemEntity.setFestival(solarFestival);
                calendarItemEntity.setCurrentDay(false);
                calendarItemEntities.add(calendarItemEntity);
            }
        }

        int totalSize = calendarItemEntities.size();
        int MAX_COUNT = 28;
        if (totalSize > MAX_COUNT) {
            if (totalSize <= 35) {
                //共5行
                if (currentDayIndex <= 17) {
                    return calendarItemEntities.subList(0, MAX_COUNT);
                } else {
                    return calendarItemEntities.subList(7, 35);
                }
            } else {
                //共6行
                if (currentDayIndex <= 20) {
                    return calendarItemEntities.subList(0, MAX_COUNT);
                } else {
                    return calendarItemEntities.subList(14, totalSize);
                }
            }
        }
        return calendarItemEntities;
    }

    //阳历年
    private int year;

    //阳历yue
    private int month;

    //阳历日
    private int day;

    //阳历字符串年
    private String strYear;

    public String getStrYear() {
        return strYear;
    }

    //阳历几月几号
    private String strDateDay;

    public String getStrDateDay() {
        return strDateDay;
    }

    //中文星期几
    private String cnWeek;

    public String getCnWeek() {
        return cnWeek;
    }

    //第几周
    private String strWeekNum;

    public String getStrWeekNum() {
        return strWeekNum;
    }

    //干支纪年
    private String trunkBranchYear;

    public String getTrunkBranchYear() {
        return trunkBranchYear;
    }

    //生肖
    private String twelveAnimal;

    public String getTwelveAnimal() {
        return twelveAnimal;
    }

    private String currentFestival;

    public String getCurrentFestival() {
        return currentFestival;
    }

    //农历年
    private String nlYear;

    //农历月
    private String nlMonth;

    //农历日
    private String nlDay;

    public String getNLMonthAndDay() {
        return String.format(Locale.getDefault(), "%s%s", calendarData.nlMonth, calendarData.nlDay);
    }

    //阳历月天数
    private int monthDaysCount;

    private HashMap<String, String> solar24Terms;

    public HashMap<String, String> getSolar24Terms() {
        return solar24Terms;
    }

    //日历当月1号开始位置  星期一 index=0 ------ 星期天 index=6
    private int beginIndex;

    private List<CalendarItemEntity> calendarItemEntities;

    public List<CalendarItemEntity> getCalendarItemEntities() {
        return calendarItemEntities;
    }

    public static class CalendarItemEntity {
        private int isLastOrNext; //-1-代表上月  0-代表当月   1-代表下月
        private int ylDay;
        private String nlDay;
        private boolean isCurrentDay;
        private String festival;

        public int getIsLastOrNext() {
            return isLastOrNext;
        }

        public void setIsLastOrNext(int isLastOrNext) {
            this.isLastOrNext = isLastOrNext;
        }

        public int getYlDay() {
            return ylDay;
        }

        public void setYlDay(int ylDay) {
            this.ylDay = ylDay;
        }

        public String getNlDay() {
            return nlDay;
        }

        public void setNlDay(String nlDay) {
            this.nlDay = nlDay;
        }

        public boolean isCurrentDay() {
            return isCurrentDay;
        }

        public void setCurrentDay(boolean currentDay) {
            isCurrentDay = currentDay;
        }

        public String getFestival() {
            return festival;
        }

        public void setFestival(String festival) {
            this.festival = festival;
        }

        @NonNull
        @Override
        public String toString() {
            return "\n CalendarItemEntity{" +
                    "\n    isLastOrNext=" + isLastOrNext +
                    "\n    ylDay=" + ylDay +
                    "\n    nlDay='" + nlDay + '\'' +
                    "\n    isCurrentDay=" + isCurrentDay +
                    "\n    festival='" + festival + '\'' +
                    "\n}";
        }
    }

    @NonNull
    @Override
    public String toString() {
        return "CalendarData{" +
                "\n strYear='" + strYear + '\'' +
                "\n strDateDay='" + strDateDay + '\'' +
                "\n cnWeek='" + cnWeek + '\'' +
                "\n strWeekNum='" + strWeekNum + '\'' +
                "\n trunkBranchYear='" + trunkBranchYear + '\'' +
                "\n twelveAnimal='" + twelveAnimal + '\'' +
                "\n solar24Terms='" + solar24Terms.toString() + '\'' +
                "\n beginIndex='" + beginIndex + '\'' +
                "\n nlYear='" + nlYear + '\'' +
                "\n nlMonth='" + nlMonth + '\'' +
                "\n nlDay='" + nlDay + '\'' +
                "\n calendarItemEntities=" + calendarItemEntities.toString() +
                "\n}";
    }

    private String getSolarFestival(int[] ints,String strNlDay,int year,int month,int day){
        String solarFestival = "";
        int nlMonthCount = LunarUtil.daysInNLMonth(ints[0], ints[1]);
        if(ints[3]!=1){ //不是闰月
            if(ints[1]==12){
                if(nlMonthCount ==29){
                    if(ints[2] ==29){
                        solarFestival ="除夕";
                    }
                }else{
                    //30天
                    if(ints[2] ==30){
                        solarFestival ="除夕";
                    }
                }
            }else{
                solarFestival =  LunarUtil.getTraditionFestival(strNlDay);
                LogUtils.d(TAG,"VERY GOOD IS strNlDay:"+strNlDay + "--solarFestival:"+solarFestival);
            }
        }
        if(TextUtils.isEmpty(solarFestival)){
            solarFestival = has24Terms(year, month, day);
        }
        if(TextUtils.isEmpty(solarFestival)){
            solarFestival = LunarUtil.getSolarFestival(month, day);
        }
        return solarFestival;
    }

    private String has24Terms(int year,int month,int day){
        String lastM;
        if (month <= 9) {
            lastM = "0" + month;
        } else {
            lastM = String.valueOf(month);
        }
        String lastD;
        if (day <= 9) {
            lastD = "0" + day;
        } else {
            lastD = String.valueOf(day);
        }
        String lastYMD = year + lastM + lastD;
        boolean hasContains = calendarData.solar24Terms.containsKey(lastYMD);
        String solarFestival = "";
        if(hasContains){
            solarFestival =  calendarData.solar24Terms.get(lastYMD);
        }
        return solarFestival;
    }

    private int[] getLastMonthAndYear(int year, int month) {
        int[] lastYM = new int[2];
        if (month == 1) {
            lastYM[0] = year - 1;
            lastYM[1] = 12;
        } else {
            lastYM[0] = year;
            lastYM[1] = month - 1;
        }
        return lastYM;
    }

    private int[] getNextMonthAndYear(int year, int month) {
        int[] nextYM = new int[2];
        if (month == 12) {
            nextYM[0] = year + 1;
            nextYM[1] = 1;
        } else {
            nextYM[0] = year;
            nextYM[1] = month + 1;
        }
        return nextYM;
    }

    private String getCNWeek(int euWeek) {
        switch (euWeek) {
            case 1:
                return "星期天";
            case 2:
                return "星期一";
            case 3:
                return "星期二";
            case 4:
                return "星期三";
            case 5:
                return "星期四";
            case 6:
                return "星期五";
            default:
                return "星期六";
        }
    }

    private String getTwelveAnimal(int year) {
        int yuShu = year % 12;
        switch (yuShu) {
            case 4:
                return "鼠";
            case 5:
                return "牛";
            case 6:
                return "虎";
            case 7:
                return "兔";
            case 8:
                return "龙";
            case 9:
                return "蛇";
            case 10:
                return "马";
            case 11:
                return "羊";
            case 0:
                return "猴";
            case 1:
                return "鸡";
            case 2:
                return "狗";
            case 3:
                return "猪";
            default:
                return "";
        }
    }

    //不是角标，而是占位数量
    private int getBeginIndex(int euWeek) {
        switch (euWeek) {
            case 2:  //星期一
                return 0;
            case 3:  //星期二
                return 1;
            case 4:  //星期三
                return 2;
            case 5:  //星期四
                return 3;
            case 6:  //星期五
                return 4;
            case 7:  //星期六
                return 5;
            default: //星期天
                return 6;
        }

    }
}
